#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
定义系统访问对象
"""

__author__ = 'Lei Chen'

import requests
import logging
from api import config
from api.exceptions import *


class Result(object):

    def __init__(self, response):
        self.json = response.json()
        self.status_code = response.status_code
        self.data = self._data()
        self.meta = self._meta()
        self.success = self._success()
        self.message = self._message()
        self._default_auth = True
        self.headers = response.headers

    def _meta(self):
        if self.json.get('meta'):
            return self.json.get('meta')

    def _data(self):
        if self.json.get('data'):
            return self.json.get('data')

    def _success(self):
        if self.status_code == 200:
            if self.meta:
                return self.meta.get('success')
            else:
                return self.json.get('status') == 'success'

        return False

    def _message(self):
        if self.meta:
            return self.meta.get('message')
        else:
            return self.json

    def get(self, name, num=0):
        if self.data:
            if isinstance(self.data, list):
                return self.data[num].get(name)
            elif isinstance(self.data, dict):
                return self.data.get(name)
        return None


class Http(object):
    def __init__(self, system, parser):
        self._config = parser.config(system)
        self.system = system
        self._base_headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
        self._base_params = {}
        self._base_url = self._config.server_url
        self._default_auth = False

    def _headers(self, headers={}):
        if headers:
            _headers = self._base_headers
            for k, v in headers.items():
                _headers[k] = v
            return _headers
        else:
            return self._base_headers

    def _params(self, params={}):
        if params:
            _params = self._base_params
            for k, v in params.items():
                _params[k] = v
            return _params
        else:
            return self._base_params

    def _url(self, url):
        url = '{0}/{1}'.format(self._base_url, url)
        url = url.replace('///', '/').replace('//', '/').replace(':/', '://')
        return url

    def _auth(self, headers, params):
        pass

    def request(self, method, url, params={}, headers={}, auth=False):
        try:
            auth = auth or self._default_auth
            if auth:
                self._auth(headers, params)
            params = self._params(params)
            headers = self._headers(headers)
            response = requests.request(method, self._url(url),
                                        headers=headers,
                                        params=params,
                                        json=params)
        except ApiError as err:
            return Result(err.args)
        return Result(response)

    def get(self, url, params={}, headers={}, auth=False):
        return self.request('GET', url, params, headers, auth)

    def post(self, url, params={}, headers={}, auth=False):
        return self.request('POST', url, params, headers, auth)

    def put(self, url, params={}, headers={}, auth=False):
        return self.request('PUT', url, params, headers, auth)


class Web(Http):

    def __init__(self, parser):
        Http.__init__(self, 'WEB', parser)
        self._base_headers['x-domain'] = self._config.xdomain
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'

    def get_token(self):
        if not self._token_value:
            self.login()
        return self._token_value

    def _auth(self, headers, params):
        headers[self._token_name] = self.get_token()

    def send_sms(self, **kwargs):
        username = kwargs.get('username') or self._username
        params = {'phone': username, 'nationCode': '86'}
        return self.get('sendSms', params=params)

    def login(self, **kwargs):
        try:
            username = kwargs.get('username') or self._username
            password = kwargs.get('password') or self._password

            # 登录第一步 获取token
            params = {'userName': username, 'password': password}
            result = self.post('user/userLoginForStep1', params=params)
            if result.success:
                # 发送短信验证码
                token = result.get('token')
                result = self.send_sms(username=username, token=token)

                if result.success:
                    # 登录第二步
                    params = {'phone': username, 'phoneCode': '6666', 'email': '', 'emailCode': '', 'googleCode': '',
                              'token': token}
                    headers = {self._token_name: token}
                    result = self.post('user/userLoginForStep2', params=params, headers=headers)

                    if result.success:
                        self._token_value = token
                else:
                    raise LoginError(result.json)
            else:
                raise LoginError(result.json)

            return self._token_value
        except Exception as err:
            logging.error(err)
            return {'err': err}


class Api(Http):

    def __init__(self, parser):
        Http.__init__(self, 'API', parser)
        self.accessKey = self._config.accessKey
        self.secretKey = self._config.secretKey
        self.ip = self._config.ip
        self.web = Web(parser)

    def get_accessKey(self, **kwargs):

        ip = kwargs.get('ip') or self.ip
        remark = kwargs.get('remark') or 'test'
        if self.accessKey:
            return self.accessKey

        web = self.web

        result = web.get('userApi', auth=True)
        if result.success:
            if result.get('accessKey'):
                self.secretKey = result.get('secretKey')
                self.accessKey = result.get('accessKey')
            else:
                # 发送验证码
                result = web.send_sms()

                if result.success:
                    # 获取授权码
                    params = {'phoneCode': '6666', 'emailCode': '', 'googleCode': ''}
                    result = web.get('userApi/secretKey', params=params, auth=True)

                    if result.success and result.get('accessKey'):
                        _accessKey = result.get('accessKey')
                        _secretKey = result.get('secretKey')

                        # 添加备注/ip
                        params = {'remark': remark, 'ip': ip, 'accessKey': _accessKey,
                                  'secretKey': _secretKey}
                        headers = {'Content-Type': 'application/json'}
                        result = web.post('userApi', params=params, headers=headers, auth=True)
                        if result.success:
                            self.accessKey = _accessKey
                            self.secretKey = _secretKey
                    else:
                        raise AuthError(result)
                else:
                    raise AuthError(result)
        else:
            raise AuthError(result)

        return self.accessKey

    def _auth(self, headers, params):
        params['accessKey'] = self.get_accessKey()


class Admin(Http):

    def __init__(self, parser):
        Http.__init__(self, 'ADMIN', parser)
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'

    def get_token(self):
        if not self._token_value:
            self.login()
        return self._token_value

    def _auth(self, headers, params):
        headers[self._token_name] = self.get_token()

    def send_sms(self, **kwargs):
        username = kwargs.get('username') or self._username
        password = kwargs.get('password') or self._password
        params = {'userName': username, 'password': password, 'type': '0'}
        return self.post('sendCode', params=params)

    def login(self, **kwargs):
        try:
            username = kwargs.get('username') or self._username
            password = kwargs.get('password') or self._password

            # 登录第一步 获取token
            params = {'userName': username, 'password': password}
            headers = {'Content-Type': 'application/json; charset=utf-8'}
            result = self.post('checkLogin', params=params, headers=headers)
            if result.success:
                # 发送短信验证码
                result = self.send_sms()

                if result.success:
                    # 登录第二步
                    params = {'userName': username, 'password': password, 'type': '0', 'code': '6666'}
                    result = self.post('login', params=params)

                    if result.success:
                        self._token_value = result.headers.get('authorization')
                else:
                    raise LoginError(result.json)
            else:
                raise LoginError(result.json)

            return self._token_value
        except Exception as err:
            logging.error(err)
            return {'err': err}


class Wallet(Admin):

    def __init__(self, parser):
        Http.__init__(self, 'WALLET', parser)
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'


class Partner(Http):

    def __init__(self, parser):
        Http.__init__(self, 'PARTNER', parser)
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'

    def get_token(self):
        if not self._token_value:
            self.login()
        return self._token_value

    def _auth(self, headers, params):
        headers[self._token_name] = self.get_token()

    def send_sms(self, **kwargs):
        username = kwargs.get('username') or self._username
        password = kwargs.get('password') or self._password
        params = {'userName': username, 'password': password, 'type': '0', 'platform': 'MERCHANT'}
        return self.post('partnerAdmin/sendCode', params=params)

    def login(self, **kwargs):
        try:
            username = kwargs.get('username') or self._username
            password = kwargs.get('password') or self._password

            # 登录第一步 获取token
            params = {'userName': username, 'password': password, 'platform': 'MERCHANT'}
            headers = {'Content-Type': 'application/json; charset=utf-8'}
            result = self.post('partnerAdmin/checkLogin', params=params, headers=headers)
            if result.success:
                # 发送短信验证码
                result = self.send_sms()

                if result.success:
                    # 登录第二步
                    params = {'userName': username, 'password': password, 'type': '0', 'platform': 'MERCHANT',
                              'code': '6666'}
                    result = self.post('partnerAdmin/login', params=params)

                    if result.success:
                        self._token_value = result.get('token')
                else:
                    raise LoginError(result.json)
            else:
                raise LoginError(result.json)

            return self._token_value
        except Exception as err:
            logging.error(err)
            return {'err': err}


class Trading(Http):

    def __init__(self, parser):
        Http.__init__(self, 'TRADING', parser)
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'

    def get_token(self):
        if not self._token_value:
            self.login()
        return self._token_value

    def _auth(self, headers, params):
        headers[self._token_name] = self.get_token()

    def send_sms(self, **kwargs):
        username = kwargs.get('username') or self._username
        password = kwargs.get('password') or self._password
        params = {'userName': username, 'password': password, 'type': '0', 'platform': 'MERCHANT'}
        return self.post('admin/sendCode', params=params)

    def login(self, **kwargs):
        try:
            username = kwargs.get('username') or self._username
            password = kwargs.get('password') or self._password

            # 登录第一步 获取token
            params = {'userName': username, 'password': password}
            headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
            result = self.post('admin/checkLogin', params=params, headers=headers)
            if result.success:
                # 发送短信验证码
                result = self.send_sms()

                if result.success:
                    # 登录第二步
                    params = {'userName': username, 'password': password, 'type': '0',
                              'code': '6666'}
                    result = self.post('admin/login', params=params)

                    if result.success:
                        self._token_value = result.get('token')
                else:
                    raise LoginError(result.json)
            else:
                raise LoginError(result.json)

            return self._token_value
        except Exception as err:
            logging.error(err)
            return {'err': err}


class App(Http):

    def __init__(self, parser):
        Http.__init__(self, 'APP', parser)
        self._base_headers['x-domain'] = self._config.xdomain
        self._token_value = None
        self._username = self._config.username
        self._password = self._config.password
        self._token_name = self._config.token_name or 'token'
        self._partnerId = self._config.partnerId
        self._partnerNo = self._config.partnerNo

    def get_token(self):
        if not self._token_value:
            self.login()
        return self._token_value

    def _auth(self, headers, params):
        headers[self._token_name] = self.get_token()

    def send_sms(self, **kwargs):
        username = kwargs.get('username') or self._username
        token = kwargs.get('token') or self.get_token()
        params = {'phone': username, 'nationCode': '86', 'partnerId': self._partnerId,
                  'partnerNo': self._partnerNo}
        return self.get('sendSms', params=params, headers={self._token_name: token})

    def login(self, **kwargs):
        try:
            username = kwargs.get('username') or self._username
            password = kwargs.get('password') or self._password

            # 登录第一步 获取token
            params = {'userName': username, 'password': password, 'partnerId': self._partnerId,
                      'partnerNo': self._partnerNo}
            result = self.post('user/userLoginForStep1', params=params)
            if result.success:
                # 发送短信验证码
                token = result.get('token')
                result = self.send_sms(username=username, token=token)

                if result.success:
                    # 登录第二步
                    params = {'phone': username, 'phoneCode': '6666', 'email': '', 'emailCode': '', 'googleCode': '',
                              'token': token, 'partnerId': self._partnerId,
                              'partnerNo': self._partnerNo}
                    headers = {self._token_name: token}
                    result = self.post('user/userLoginForStep2', params=params, headers=headers)

                    if result.success:
                        self._token_value = token
                else:
                    raise LoginError(result.json)
            else:
                raise LoginError(result.json)

            return self._token_value
        except Exception as err:
            logging.error(err)
            return {'err': err}


def main():
    # api = Api(config.ApiConfigParser())
    # response = api.auth('192.168.1.13', 'api-13')
    # logging.info(response)

    parser = config.ApiConfigParser()
    web = Web(parser)
    result = web.get('userApi', auth=True)
    print(result.json)


if __name__ == '__main__':
    main()
